package com.jacob.androidstudy.javanote;

import java.lang.reflect.*;

public class $16_反射 {
	
	/**
	 * java.lang.Class
	 * 1. Class类的对象用来描述其他类的“基因信息”。
	 * 2. 通过“基因信息”，就可以分析得到目标类的域、方法等。
	 * 3. 一种类与一个Class对象对应。一种类只有一个Class对象。
	 * 4. 和Class相关的类：java.lang.Class、java.lang.Package、java.lang.reflect.Modifier、java.lang.reflect.Field、java.lang.reflect.Constructor、java.lang.reflect.Method
	 * 
	 */
	public void Class类() {
//		如何得到某个类的Class对象。以String类为例。方法1：
		try {
			Class c1 = Class.forName("java.lang.String");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
//		如何得到某个类的Class对象。以String类为例。方法2：
		Class c2=String.class;
		
//		如何得到某个类的Class对象。以String类为例。方法3：
		Class c3="String对象".getClass();
		
		
		
		
//		得到目标类的包名
		c2.getPackage().getName();
		
//		得到目标类的修饰符
		Modifier.toString(c2.getModifiers());
		
//		得到目标类的完整类名(含包名)
		c2.getName();
		
//		得到目标类的简单类名(不含包名)
		c2.getSimpleName();
		
//		得到目标类的父类对应的Class对象
		c2.getSuperclass();
		
//		得到一个Class对象的数组，包含目标类实现的所有接口。此数组长度为0的话，说明c2没有实现任何接口。
		c2.getInterfaces();
		
//		得到目标类中含有"域名"的public域
		try {
			c2.getField("域名");
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		
//		得到一个Field对象数组, 包含目标类的所有public域.
		Field[] f2=c2.getFields();
		
//		得到目标类中含有"域名"的域
		try {
			c2.getDeclaredField("域名");
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		
//		得到一个Field对象数组, 包含目标类的所有域.
		c2.getDeclaredFields();
		
//		得到目标类的构造 方法和上面类似, 看API.
		
		
	}
	
	/**
	 * 反射的常规应用（以String类为例）
	 */
	public void 反射应用() {
//		1. 得到Class对象c
		Class c = String.class;

		try {
//			2. 通过c得到String类的对象实例o1，这种方法只能调用无参构造。
			Object o1=c.newInstance();
			
//			3.通过c得到String类的构造方法con。
			Constructor con=c.getConstructor(String.class);
			
//			4. 设置为true则指示反射的对象在使用时应该取消Java语言访问检查。这样即使是private的构造，也可以访问了。
			con.setAccessible(true);
			
//			5. 通过con得到String类的对象实例o2，这种方法无参有参构造都可以调用。
			Object o2=con.newInstance("ABC,DEF");
			
//			6. 通过c得到String类的split方法m。
			Method m=c.getMethod("split", String.class);
			
//			7. 设置为true则指示反射的对象在使用时应该取消Java语言访问检查。这样即使是private的方法，也可以访问了。
			m.setAccessible(true);
			
//			8. 通过m调用o2的split()
			m.invoke(o2, ",");
			
//			9. 通过c得到String类的CASE_INSENSITIVE_ORDER域f
			Field f=c.getField("CASE_INSENSITIVE_ORDER");
			
//			10. 设置为true则指示反射的对象在使用时应该取消Java语言访问检查。这样即使是private的域, 也可以访问了。
			f.setAccessible(true);
			
//			11. 通过f得到o2对象的CASE_INSENSITIVE_ORDER域的值。
			f.get(o2);
			
			
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		
		
	}

	public static void main(String[] args) {
		

	}

}
